

ExtGames.Game = function(config) {
    
  console.log('Creating Game');
    
  this.createHand();
  this.createPlayareas();
  this.createDeck();
  
  console.log('Creating Pack');
  this.pack = new ExtGames.Pack(config);
  
  console.log('Creating scorecard');
  this.scorecard = new ExtGames.Scorecard({
		 title: 'Scorecard',
		 collapsed: true,
		 split: true,
		 width: 400,
		 collapsible: true,
		 region: 'east'
  });  
  
  if (!this.win) {
	  
	 console.log('Creating Window');
	  
    this.win = new ExtGames.MainWindow({
      game:       this,
      unuseddeck: this.unuseddeck,
      discardpile: this.discardpile,
      playareas: this.playareas,
      hands: this.hands,
      scorecard: this.scorecard
    });
  };
  
  this.round = 0;
  
  
  
};

ExtGames.Game.prototype = {
  
  /**
   * @property inProgress
   * @type Boolean
   * true if a game is in progress
   */
  inProgress: true,
  
  round: 0,
  
  turn: 0,
  
  didPlay: false,
  
  /**
   * Resets the game
   */
  newGameClicked: function(config) {
    if (this.inProgress == true) {
	    Ext.Msg.confirm('Game in progress', "Are you sure?  You'll lose your current game", function(btn) {
	        if (btn == 'yes') {
	           var selectionWin = new ExtGames.GameSelectionWindow();
	           selectionWin.show();
	        };
	      });
	              
     }
     
  },
  
  newGame: function() {
    
	  console.log('Starting New Game');
	  	  
	  this.populateHand();
	    
	  console.log('Hand Pop');
	  
	    while (c = this.pack.getTopCard()) {
	        c.move(this.unuseddeck);
	      }
	    
	    var topCard = this.unuseddeck.getTopCard();
	    topCard.revealed = true;
		topCard.move(this.discardpile);
	    		
	    if (util.isTurn()) {
	    	
	    }
	    else {
	    	this.turn = TURN_END;
	    }
	    	    
	    console.log('New Game Started');
  },
  
  /**
   * Sets up the Deck
   */
  createDeck: function() {
	  console.log('Creating Deck');
	  
    this.unuseddeck   = new ExtGames.UnusedDeck({
    	itemId: 'unuseddeck'
    });
    
    this.discardpile   = new ExtGames.DiscardPile({
    	itemId: 'discardPile',
    	listeners: {
            'carddropped': {
            	fn: this.dropCard,
            	scope: this,
            }
          }
        });
    
  },
  

  
  
  populateHand: function() {
	  	  
	  var numCards = this.getNumberOfCardsToDeal();
	  	  	  
	  var num = util.getTurnIndex();
	  	  	  
	  for (var i = 0; i < numCards; i++) {
		  for (var j = 0; j < this.hands.length; j++) {
			  			  			  
			  var card = this.pack.getTopCard();
			  			  
			  if (num == 0) {
				  card.revealed = true;
			  }
		      			  
		      card.move(this.hands[num]);
		      		      
		      num++;
		      if (num >= this.hands.length) {
		    	  num = 0;
		      }
		  }
	  }
	  	  
	  this.hands[0].sortCards();
  },
  
  
  
  /**
   * Creates stacks components
   */
  createHand: function() {
	  
	 console.log('Creating Hand');
	  
	this.hands = [];
	  
	this.hands.push(new ExtGames.Hand({
		itemId: 'hand',
		type: 0,
		listeners: { 
            'carddropped': {
            	fn: this.dropCard,
            	scope: this,
            }
          }
 
        }));  
	
	
	var opp = util.getOpponents();
			
	for (var i = 0; i < opp.length; i++) {
		this.hands.push(new ExtGames.Hand({
			itemId: 'hand_'+opp[i].id,
			handName: opp[i].name,
			type: 1,
			listeners: {
	            'carddropped': {
	            	fn: this.dropCard,
	            	scope: this,
	            }
	          }
	 
	        }));  
	}
		
	console.log('Created '+this.hands.length+' hands');
	
  },
  
  createPlayareas: function() {
  	  this.playareas = [];
  },
  
  /**
   * Starts the game by opening the window
   */
  launch: function() {
    this.win.render();
    
    //this.pack.createCards({decks: 2});
  	//this.reformDeck();
  },
  
  didPlay: function() {
	  var didPlay = false;
	  for (var i = 0; i < this.playareas[0].length; i++) {
		  if (this.playareas[0][i].didPlay()) {
			  didPlay = true;
		  }
	  }
	  return didPlay;
  },
  
  isAllPlaysValid: function() {
	  for (var j = 0; j < this.playareas.length; j++) {
		  var didPlay = false;
		  for (var i = 0; i < this.playareas[j].length; i++) {
      		if (this.playareas[j][i].didPlay() || didPlay) {
      			didPlay = true;
      			if (this.playareas[j][i].validPlay() == false) {
      				console.log(this.playareas[j][i].itemId+' is not valid');
      				return false;
      			}
      		}
      	  }
	  }
	  return true;
  },
  
  dropCard: function(stack, card, e) {	  
	  	  
	  var from = card.location.itemId;
	  var to = stack.itemId;
	  
	  console.log('DROP CARD from '+from+' to '+to);
	  	  
	  if (from == 'hand' && to == 'hand') {
	  	  this.hands[0].rearrange(card, e);
	  	  return;
	  }
	  
	  if (this.turn == TURN_START) {
		  if (from != 'unuseddeck' && from != 'discardPile') {
		  	 return;
		  }
	  
		  if (from == 'unuseddeck') {
		  	
		  	  if (this.mayI) {
		  	     this.giveMayICards();
				 card = this.unuseddeck.getTopCard();
		  	  }
				  	
			  card.reveal();
		  }
				  
		  card.move(stack);
		  this.hands[0].sortCards();
		  this.mayI = null;
		  
		  var s = {};
		  s.from = from;
		  s.card = card.toObject();
		  util.drawCard(s);
			
		  this.turn = TURN_PLAY;
		  
		  this.win.updateStatus('You drew a '+card.toPlainText());
			  
	  }
	  else if (this.turn == TURN_PLAY) {
		  
		  if (from == 'discardPile' || from == 'unuseddeck' || from.indexOf('hand_') == 0) {
	  		return;
  	  	  }
	  
		  if (from.indexOf('play') == 0) {
			  
			  if (to == from) {
			  	  stack.rearrange(card,e);
			  	  return;
			  }
			  
			  if (card.location.isSaved(card) == true) {
			  	  return;
			  }
		  }
		 
		  if (to == 'discardPile') {
			 
			  var didPlay = this.didPlay();
			  
			  if (this.isAllPlaysValid() == false) {
				  return;
			  }
			  if (didPlay == true && this.splashOnly() == true) {
			  	  return;
			  }
			  
			  card.move(stack);
			  util.discard(this.getDiscardObject(card));
			  
			 this.turn = TURN_END;
			  
			  if (didPlay) {
				  for (var j = 0; j < this.playareas.length; j++) {
					  for (var i = 0; i < this.playareas[j].length; i++) {
						  this.playareas[j][i].saveCards();
					  }
				  }
				  
			  }
			  
			  if (this.hands[0].getNumCards() == 0) {
				  this.endRound();
			  }
			  else {
				  util.endTurn();
			  }
			  
		  }
		  else if (to.indexOf('play') == 0) {
		  			
		  	  card.move(stack);
		  		
		  	  if (this.hands[0].getNumCards() == 0) {	
			  	  
		  		var didPlay = this.didPlay();
				  
				  if (this.isAllPlaysValid() == false) {
					  return;
				  }
				
				util.discard(this.getDiscardObject(card));
				this.endRound();
			}
			else {
				var joker = stack.replaceJoker(card);
			}  
					  	
		}
		else {
			card.move(stack);
		}
	  
	}
	  
  },
  
  nextTurn: function() {
	  	  	  	  
	  if (util.isTurn()) {
		  this.turn = TURN_START;
	  }
	  	  
	  this.updateStatusTurn();
	  
	  var index = util.getTurnIndex();
	  this.hands[index].setTurn();
	  	  	  
	  index--;
	  if (index < 0) {
	  	index += util.getNumP();
	  }
	  
	  this.hands[index].removeTurn();
  },
  
  endRound: function() {
	  console.log('Round ended. You Win.');
	  
	  var scorecard = [];
	  
	  for (var i = 0; i < this.hands.length; i++) {
		  cards = this.hands[i].toObject();
		  		  
		  points = 0;
		  for (var j = 0; j < cards.length; j++) {
			  points += getCardPoints(cards[j]);
		  }
		  scorecard[i] = points;
	  }
	  
	  util.submitScores(scorecard);
	  
	  if (this.isGameEnd()) {
	  	//this.gameEnd();
	  }
	  else {
	  	this.pack.createCards({
	  		decks: NUM_DECKS
	  	});
	  	util.nextRound();
	  }
	  
  },
  
  gameEnd: function() {
  	  var winnerIds = getWinnerList(this.scorecard.getTotals());
  	  var winnerString = '';
  	  for (var i = 0; i < winnerIds.length; i++) {
  	  	 if (i > 0) {
  	  	 	winnerString += ' and ';
  	  	 }
  	  	 winnerString = util.getName(winnerIds[i]);
  	  }
  	  Ext.MessageBox.alert('And the winner is...', winnerString);
  },
  
  updateScores: function(scorecard) {
  	
	  this.scorecard.displayScores(scorecard);
	  
	  for (var i = 0; i < this.hands.length; i++) {
	  		this.hands[i].reveal();
	  }
	  
	  this.scorecard.expand(true);
	  
	  if (this.isGameEnd()) {
	  	this.gameEnd();
	  }
  },
  
  getPack: function() {
	  return this.pack;
  },
  
  getPlayAreaCards: function() {
	  var c = [];
	  for (var i = 0; i < this.playareas[0].length; i++) {
		  c[i] = this.playareas[0][i].toObject();
	  }
	  
	  return JSON.stringify(c);
  },
  
  getDiscardObject: function(card) {
	  var s = {};
	  s.card = card.toObject();
	  s.plays = [];

	  for (var j = 0; j < this.playareas.length; j++) {
		  for (var i = 0; i < this.playareas[j].length; i++) {
			  var o = this.playareas[j][i].getNewCardsObject();
			  o.pIndex = j;
			  o.aIndex = i;
			  s.plays.push(o);
		  }
	  }
	  
	  return s;
  },
  
  drewCard: function(details) {
  	    	  	   	  
	  var hand = null;
	  if (details.id == util.getMyId()) {
	  	hand = this.hands[0];
	  }
	  else {
	  	for (var i = 1; i < this.hands.length; i++) {
	  		if (this.hands[i].itemId == ('hand_'+details.id)) {
	  			hand = this.hands[i];
	  		}
	  	}
	  }
	  	  	  
	  var card = null;
	  if (details.from == 'unuseddeck') {
	  	card = this.unuseddeck.getTopCard();
	  }
	  else {
	  	card = this.discardpile.getTopCard();
	  }
	  	  
	  if (details.id == util.getMyId()) {
	  	card.reveal();
	  }
	  else {
	  	card.hide();
	  }
	  	  
	  card.move(hand);
	  
	  this.updateStatusDraw(util.getName(details.id), details.from);
	  //card.reveal();
  },
  
  discardedCard: function(details) {
	  var turnIndex = util.getTurnIndex();
	  
	  console.log('Turn i: '+turnIndex);
	  //var turnView = 4-turnIndex;
	  var hand = this.hands[turnIndex];
	  
	  console.log(this.hands.length);
	  console.log(hand.itemId);
	  	  	  
	  // XXX: Breaks somewhere in here
	  
	  for (var i = 0; i < details.plays.length; i++) {
		  
		  var pIndex = details.plays[i].pIndex;
		  var aIndex = details.plays[i].aIndex;
		  
		  pIndex = (pIndex+turnIndex)%util.getNumP();
		  var areas = this.playareas[pIndex];
		  
		  var area = areas[aIndex];
		  
		  for (var j = 0; j < details.plays[i].cards.length; j++) {
			  var card = hand.findCard(details.plays[i].cards[j]);			  
			  card.move(area, card.pos);
		  }
		  
		  area.saveCards();
	  }
	  
	  	  
	  var card = hand.findCard(details.card);
	  console.log(card.toString());
	  
	  card.move(this.discardpile);
	  
	  card.reveal();
  },
  
  reformDeck: function() {
  	
  	for (var i = 0; i < this.hands.length; i++) {
  		this.hands[i].destroyCards();
  	}
  	
  	for (var i = 0; i < this.playareas.length; i++) {
  		for (var j = 0; j < this.playareas[i].length; j++) {
  			this.playareas[i][j].destroyCards();
  		}
  	}
  	this.discardpile.destroyCards();
  	this.unuseddeck.destroyCards();
  	
  	this.win.removeComponents();
  	  	
  	this.round++;
  	 
  	//this.createDeck();
  	this.createHand();
  	this.createPlayareas();
  	this.populateHand();
  	
  	while (c = this.pack.getTopCard()) {
	        c.move(this.unuseddeck);
	}
  	
  	while (c = this.pack.getTopCard()) {
        c.move(this.unuseddeck);
    }
    
    
	
	
	this.unuseddeck.addListener('afterlayout', this.unuseddeck.applyClasses);
	this.discardpile.addListener('afterlayout', this.discardpile.applyClasses);	
	this.discardpile.addListener('carddropped', this.dropCard, this);	
		
	this.win.redraw(this.hands, this.playareas);
	
	var topCard = this.unuseddeck.getTopCard();
	topCard.move(this.discardpile);
	topCard.reveal();
	
	
	this.scorecard.collapse(true);
	
	this.nextTurn();
  	
  },
  
  splashOnly: function() {
  	return false
  },
  
  updateStatusTurn: function() {
	  var s = 'It is '+util.getTurnName() + '\'s turn';
	  this.win.updateStatus(s);
  },
  
  updateStatusDraw: function(name, pile) {
	  if (pile == 'discardPile') {
		  pile = 'Discard Pile';
	  }
	  else {
		  pile = 'Deck';
	  }
	  var s = name + ' has drawn a card from the ' + pile;
	  this.win.updateStatus(s);
  }
  
  
};